package com.jshan.utils;

import com.jshan.base.entity.SysContent;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

@Component
public class ExportDocUtils {

    public void exportWord(SysContent content, HttpServletResponse response) throws IOException {
        // 用英文模板初始化
        InputStream templateStream = this.getClass().getResourceAsStream("/templates/template.docx");
        XWPFDocument document = new XWPFDocument(templateStream);

        // 清空模板内容（只保留样式）
        int paraSize = document.getParagraphs().size();
        for (int i = 0; i < paraSize; i++) {
            document.removeBodyElement(0);
        }
        int tableSize = document.getTables().size();
        for (int i = 0; i < tableSize; i++) {
            document.removeBodyElement(0);
        }

        // 输出所有样式ID和名称，便于调试
        org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles ctStyles = null;
        try {
            ctStyles = (org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles) document.getStyles().getClass()
                    .getMethod("getCTStyles").invoke(document.getStyles());
        } catch (Exception e) {
            try {
                ctStyles = (org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles) document.getStyles()
                        .getClass().getMethod("getUnderlyingStyles").invoke(document.getStyles());
            } catch (Exception ex) {
                ctStyles = null;
            }
        }
        if (ctStyles != null) {
            for (org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle ctStyle : ctStyles.getStyleList()) {
                String styleId = ctStyle.getStyleId();
                String name = ctStyle.getName() != null ? ctStyle.getName().getVal() : "";
                System.out.println("StyleId: " + styleId + ", Name: " + name);
            }
        }

        // 插入标题
        XWPFParagraph titleParagraph = document.createParagraph();
        titleParagraph.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun titleRun = titleParagraph.createRun();
        titleRun.setText(content.getTitle());
        titleRun.setBold(true);
        titleRun.setFontSize(16);
        titleRun.setFontFamily("Microsoft YaHei");
        titleRun.addBreak();

        // 解析HTML内容
        Document htmlDoc = Jsoup.parse(content.getContent());
        processHtmlContent(document, htmlDoc.body());
        // 设置响应头
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        String fileName = URLEncoder.encode(content.getTitle(), StandardCharsets.UTF_8) + ".docx";
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        // 写入响应
        document.write(response.getOutputStream());
        document.close();
    }

    private void processHtmlContent(XWPFDocument document, Element element) {
        for (Node node : element.childNodes()) {
            if (node instanceof TextNode) {
                String text = ((TextNode) node).text().trim();
                if (!text.isEmpty()) {
                    XWPFParagraph paragraph = document.createParagraph();
                    XWPFRun run = paragraph.createRun();
                    run.setText(text);
                    run.setFontSize(12);
                    run.setFontFamily("SimSun");
                }
            } else if (node instanceof Element) {
                Element elem = (Element) node;
                String tagName = elem.tagName().toLowerCase();

                XWPFParagraph paragraph = document.createParagraph();
                XWPFRun run = paragraph.createRun();

                switch (tagName) {
                    case "h1":
                        setParagraphStyle(paragraph, "Heading1");
                        run.setText(elem.text());
                        run.setFontFamily("SimSun");
                        break;
                    case "h2":
                        setParagraphStyle(paragraph, "Heading2");
                        run.setText(elem.text());
                        run.setFontFamily("SimSun");
                        break;
                    case "h3":
                        setParagraphStyle(paragraph, "Heading3");
                        run.setText(elem.text());
                        run.setFontFamily("SimSun");
                        break;
                    case "h4":
                        setParagraphStyle(paragraph, "Heading4");
                        run.setText(elem.text());
                        run.setFontFamily("SimSun");
                        break;
                    case "img":
                        insertImage(run, elem);
                        break;
                    case "p":
                        processParagraphContent(paragraph, elem);
                        break;
                    case "ul":
                    case "ol":
                        processListContent(document, elem, tagName.equals("ol"));
                        break;
                    case "table":
                        processTableContent(document, elem);
                        break;
                    default:
                        run.setText(elem.text());
                        run.setFontSize(12);
                        run.setFontFamily("SimSun");
                }
            }
        }
    }

    private void setParagraphStyle(XWPFParagraph paragraph, String style) {
        paragraph.setStyle(style);
    }

    private void processParagraphContent(XWPFParagraph paragraph, Element element) {
        for (Node node : element.childNodes()) {
            XWPFRun run = paragraph.createRun();
            run.setFontSize(12);
            run.setFontFamily("SimSun");

            if (node instanceof TextNode) {
                String text = ((TextNode) node).text().trim();
                if (!text.isEmpty()) {
                    run.setText(text);
                }
            } else if (node instanceof Element) {
                Element elem = (Element) node;
                String tagName = elem.tagName().toLowerCase();

                switch (tagName) {
                    case "img":
                        insertImage(run, elem);
                        break;
                    case "strong":
                    case "b":
                        run.setBold(true);
                        run.setText(elem.text());
                        break;
                    case "em":
                    case "i":
                        run.setItalic(true);
                        run.setText(elem.text());
                        break;
                    case "u":
                        run.setUnderline(UnderlinePatterns.SINGLE);
                        run.setText(elem.text());
                        break;
                    case "br":
                        run.addBreak();
                        break;
                    default:
                        run.setText(elem.text());
                }
            }
        }
    }

    private void insertImage(XWPFRun run, Element elem) {
        String imgUrl = elem.attr("src");
        try (InputStream imgStream = new URL(imgUrl).openStream()) {
            String ext = imgUrl.substring(imgUrl.lastIndexOf('.') + 1).toLowerCase();
            int picType = getPictureType(ext);
            run.addPicture(imgStream, picType, imgUrl, Units.toEMU(225), Units.toEMU(225));
        } catch (Exception e) {
            run.setText("[图片加载失败]");
        }
    }

    private int getPictureType(String ext) {
        switch (ext) {
            case "emf":
                return XWPFDocument.PICTURE_TYPE_EMF;
            case "wmf":
                return XWPFDocument.PICTURE_TYPE_WMF;
            case "pict":
                return XWPFDocument.PICTURE_TYPE_PICT;
            case "jpeg":
            case "jpg":
                return XWPFDocument.PICTURE_TYPE_JPEG;
            case "png":
                return XWPFDocument.PICTURE_TYPE_PNG;
            case "dib":
                return XWPFDocument.PICTURE_TYPE_DIB;
            case "gif":
                return XWPFDocument.PICTURE_TYPE_GIF;
            case "tiff":
                return XWPFDocument.PICTURE_TYPE_TIFF;
            case "eps":
                return XWPFDocument.PICTURE_TYPE_EPS;
            case "bmp":
                return XWPFDocument.PICTURE_TYPE_BMP;
            case "wpg":
                return XWPFDocument.PICTURE_TYPE_WPG;
            default:
                return XWPFDocument.PICTURE_TYPE_PNG;
        }
    }

    private void processListContent(XWPFDocument document, Element listElement, boolean isOrdered) {
        int itemNumber = 1;
        for (Element item : listElement.select("li")) {
            XWPFParagraph paragraph = document.createParagraph();
            paragraph.setIndentationLeft(720); // 设置缩进
            XWPFRun run = paragraph.createRun();
            run.setFontSize(12);
            run.setFontFamily("SimSun");

            if (isOrdered) {
                run.setText(itemNumber + ". " + item.text());
                itemNumber++;
            } else {
                run.setText("• " + item.text());
            }
        }
    }

    private void processTableContent(XWPFDocument document, Element tableElement) {
        Elements rows = tableElement.select("tr");
        if (rows.isEmpty())
            return;

        int numRows = rows.size();
        int numCols = rows.first().select("td,th").size();
        if (numCols == 0)
            return;

        XWPFTable table = document.createTable(numRows, numCols);
        table.setWidth("100%");

        for (int i = 0; i < rows.size(); i++) {
            Element row = rows.get(i);
            Elements cells = row.select("td,th");
            for (int j = 0; j < cells.size(); j++) {
                Element cell = cells.get(j);
                XWPFTableCell tableCell = table.getRow(i).getCell(j);

                // 设置单元格样式
                XWPFParagraph paragraph = tableCell.getParagraphArray(0);
                if (paragraph == null) {
                    paragraph = tableCell.addParagraph();
                }
                paragraph.setAlignment(ParagraphAlignment.CENTER);

                XWPFRun run = paragraph.createRun();
                run.setText(cell.text());
                run.setFontSize(12);
                run.setFontFamily("SimSun");

                // 如果是表头，设置加粗
                if (cell.tagName().equals("th")) {
                    run.setBold(true);
                }
            }
        }

        // 添加一个空行
        document.createParagraph().createRun().addBreak();
    }
}
